前言
RePlugin 是今年360技术团队GMTC大会公布的插件化方案。360对插件化的技术探索及优化,在近几年是相当有技术沉淀的。从 DroidPlugin 到 RePlugin, 确实有值得学习的地方。
本文先来简单分析下 RePlugin 的基本原理。
一、引子
普通的: Application extends ContextWrapper, 其中 attachBaseContext() 是从 ContextWrapper 继承过来的,在 Application 的 attach() 中 attachBaseContext() 会被调用:
|
|
Application 的 attachBaseContext() 方法 在 attach时被调用。那么 这个 attach() 方法是什么时机被调用呢?在 Instrumentation 类中,找到答案:
|
|
创建 Application 时,会将 Context attach 到 Application 上
另外,后面对于 类加载 知识也是必要的,再做一次复习。
可参考之前写的文章:
https://fenglincanyi.github.io/2016/11/17/Android%20%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%88%9D%E6%8E%A2/
二、Hook时机及Hook点
RePlugin 从 Application 就开始下手了, RePlugin 的 hook 时机:
在 application 的 attachBaseContext 方法中 初始化 Replugin 时(不管是哪种接入方式,都会调用):
|
|
在 RePlugin.java 中:
|
|
PMF.java 中:
|
|
在 PatchClassLoaderUtils.java 中,进行 hook 操作; 所以, 是在 attachBaseContext() 时 做的 classloader 的 hook。
我们具体来看看:
|
|
这里, 从 baseContext (makeApplication 时创建的 ContextImpl)获取到 mPackageInfo (是 LoadedApk 的实例), 进而 再获取到 mPackageInfo的私有属性 mClassLoader. 拿到 classLoader 了,就可以进行 classLoader 的替换工作了.
三、Hook实现过程
先不直接说怎么做的,我们先看看 这个 mClassLoader 是怎么来的?
在 LoadedApk.Java 中,构造方法里:
|
|
继续跟进,
|
|
其中:SystemClassLoader 是 抽象类ClassLoader 的一个静态类:
|
|
此时,就看到了熟悉的 PatchClassLoader:
|
|
我们再次回到 上面的 classLoader 替换步骤中, 那么 RepluginClassLoader 就 替换了 PathClassLoader. 后面的 类加载 过程 就依赖于 RePluginClassLoader 来工作了。
其中,oClassLoader 被赋值,就是 原始的 PathClassLoader
下个阶段:RePluginClassLoader 的 loadClass 过程的更改:
首先,原始的ClassLoader 的 loadClass 过程:(路径: Android/sdk/platforms/android-25/android.jar!/java/lang/ClassLoader.class)
|
|
下面是 RePluginClassLoader 的 实现:
|
|
之后,PmBase 的 loadClass 过程:
|
|
附录
相关资料:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1223/2205.html
http://www.jianshu.com/p/9c96b68f5ee6
https://github.com/Qihoo360/RePlugin/tree/dev/replugin-host-library
https://fenglincanyi.github.io/2016/11/17/Android%20%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%88%9D%E6%8E%A2/